#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Android应用分析器
"""

from pathlib import Path
from typing import Dict, List, Any, Optional
from datetime import datetime

from src.analyzers.base import BaseAnalyzer
from src.models.result import AnalysisResult, FrameworkInfo, AppInfo
from src.utils.logger import get_logger

class AndroidAnalyzer(BaseAnalyzer):
    """Android应用程序分析器"""

    # Android应用程序框架签名
    FRAMEWORK_SIGNATURES = {
        "Native Android": {
            "files": [r"AndroidManifest\.xml$", r"\.java$", r"\.kt$", r"\.xml$"],
            "patterns": [
                r"android\.",
                r"androidx\.",
                r"setContentView",
                r"activity_main"
            ],
            "category": "原生框架",
            "main_framework": True
        },
        "Flutter": {
            "files": [r"libflutter\.so$", r"flutter_assets", r"isolate_snapshot_data"],
            "patterns": [
                r"io\.flutter",
                r"flutterEngine",
                r"flutter\.jar"
            ],
            "category": "跨平台框架",
            "main_framework": True
        },
        "React Native": {
            "files": [r"libreactnativejni\.so$", r"ReactAndroid", r"\.jsbundle$"],
            "patterns": [
                r"com\.facebook\.react",
                r"ReactActivity",
                r"ReactNative"
            ],
            "category": "跨平台框架",
            "main_framework": True
        },
        "Xamarin": {
            "files": [r"libmonodroid\.so$", r"Mono\.", r"Xamarin\."],
            "patterns": [
                r"mono\.",
                r"Xamarin",
                r"Mono.Android"
            ],
            "category": "跨平台框架",
            "main_framework": True
        },
        "Unity": {
            "files": [
                r".*\.unity$",
                r".*Unity.*\.dll$",
                r".*\/UnityEngine\/.*",
                r".*\/unity\/.*",
                r".*\/libunity\.so$"
            ],
            "patterns": [
                r"UnityEngine",
                r"UnityPlayer",
                r"com\.unity\."
            ],
            "category": "游戏引擎",
            "is_main_framework": True,
            "features": ["跨平台游戏引擎", "3D/2D游戏开发", "C#编程"]
        },
        "Unreal Engine": {
            "files": [
                r".*\.uproject$",
                r".*\.uasset$",
                r".*\/UE4\/.*",
                r".*\/UnrealEngine\/.*",
                r".*libUE4\.so$"
            ],
            "patterns": [
                r"com\.epicgames\.ue4",
                r"UE4Activity",
                r"UnrealEngine"
            ],
            "category": "游戏引擎",
            "is_main_framework": True,
            "features": ["高品质3D游戏引擎", "C++编程", "蓝图可视化编程"]
        },
        "Cocos2d-x": {
            "files": [
                r".*cocos2d.*\.jar$",
                r".*\/cocos\/.*",
                r".*\/cocos2d\/.*",
                r".*libcocos2d.*\.so$"
            ],
            "patterns": [
                r"org\.cocos2d\.",
                r"cocos2d::",
                r"cocos2dx"
            ],
            "category": "游戏引擎",
            "is_main_framework": True,
            "features": ["轻量级2D游戏引擎", "C++/JavaScript编程", "跨平台开发"]
        },
        "Godot": {
            "files": [
                r".*\.godot$",
                r".*\.tscn$",
                r".*\.gdscript$",
                r".*\/godot\/.*",
                r".*libgodot.*\.so$"
            ],
            "patterns": [
                r"org\.godotengine\.",
                r"GodotApp",
                r"extends Node"
            ],
            "category": "游戏引擎",
            "is_main_framework": True,
            "features": ["开源游戏引擎", "GDScript编程", "节点系统", "2D/3D游戏开发"]
        },
        "LibGDX": {
            "files": [
                r".*gdx.*\.jar$",
                r".*\/libgdx\/.*",
                r".*\/com\/badlogic\/gdx\/.*"
            ],
            "patterns": [
                r"com\.badlogic\.gdx\.",
                r"implements ApplicationListener",
                r"extends Game"
            ],
            "category": "游戏引擎",
            "is_main_framework": True,
            "features": ["Java游戏开发框架", "2D/3D游戏开发", "跨平台"]
        },
        "GameMaker": {
            "files": [
                r".*\/YoYo\/.*",
                r".*YYAndroidPackageManager.*"
            ],
            "patterns": [
                r"com\.yoyogames\.",
                r"GMRunner",
                r"YYAndroidPackageManager"
            ],
            "category": "游戏引擎",
            "is_main_framework": True,
            "features": ["易用性高的游戏开发工具", "GML编程语言", "视觉化编辑器"]
        },
        "Kotlin": {
            "files": [r"kotlin\-stdlib\.jar$", r"\.kt$"],
            "patterns": [
                r"kotlin\.",
                r"KotlinCompanionObject",
                r"@Composable"
            ],
            "category": "编程语言",
            "main_framework": False
        },
        "Java": {
            "files": [r"\.java$", r"\.class$", r"\.dex$"],
            "patterns": [
                r"import java\.",
                r"extends Activity",
                r"implements.*Listener"
            ],
            "category": "编程语言",
            "main_framework": False
        },
        "Jetpack Compose": {
            "files": [r"androidx\.compose", r"compose\-.*\.jar"],
            "patterns": [
                r"@Composable",
                r"import androidx\.compose",
                r"ComposeView"
            ],
            "category": "UI框架",
            "main_framework": False
        },
        "Room": {
            "files": [r"androidx\.room", r"room\-.*\.jar"],
            "patterns": [
                r"@Entity",
                r"@Dao",
                r"import androidx\.room",
                r"RoomDatabase"
            ],
            "category": "数据库",
            "main_framework": False
        },
        "Firebase": {
            "files": [r"google\-services\.json", r"com\.google\.firebase"],
            "patterns": [
                r"FirebaseApp",
                r"FirebaseAuth",
                r"FirebaseDatabase",
                r"import com\.google\.firebase"
            ],
            "category": "云服务",
            "main_framework": False
        },
        "Weex": {
            "files": [r"weex\-sdk.*\.jar$", r"weex\-main\.js$", r"libweexcore\.so$"],
            "patterns": [
                r"com\.taobao\.weex",
                r"weex\.core",
                r"WXSDKInstance"
            ],
            "category": "跨平台框架",
            "main_framework": True,
            "features": ["阿里巴巴开发的跨平台框架", "类似React Native的开发体验", "高性能渲染"]
        },
        "阿里EMAS": {
            "files": [r"aliyun\-emas.*\.jar$", r"alicloud\-android\-emas.*\.aar$"],
            "patterns": [
                r"com\.alibaba\.emas",
                r"com\.aliyun\.ams",
                r"EMASService"
            ],
            "category": "应用服务框架",
            "main_framework": False,
            "features": ["阿里移动服务", "应用监控", "推送服务", "热修复", "用户反馈"]
        },
        "腾讯MMKV": {
            "files": [r"libmmkv\.so$", r"MMKV\.java$"],
            "patterns": [
                r"com\.tencent\.mmkv",
                r"MMKV\.initialize",
                r"MMKV\.defaultMMKV"
            ],
            "category": "数据存储",
            "main_framework": False,
            "features": ["腾讯开发的高性能键值存储框架", "基于mmap的存储方式", "跨平台支持"]
        },
        "腾讯Tinker": {
            "files": [r"tinker\-android\-.*\.jar$", r"tinker\.xml$"],
            "patterns": [
                r"com\.tencent\.tinker",
                r"TinkerApplication",
                r"TinkerInstaller"
            ],
            "category": "热修复框架",
            "main_framework": False,
            "features": ["腾讯开发的热修复框架", "支持全量替换", "高兼容性"]
        },
        "腾讯Bugly": {
            "files": [r"bugly.*\.jar$", r"libBugly\.so$"],
            "patterns": [
                r"com\.tencent\.bugly",
                r"CrashReport",
                r"Bugly\.init"
            ],
            "category": "应用监控",
            "main_framework": False,
            "features": ["腾讯开发的应用监控框架", "崩溃分析", "运行时异常捕获"]
        },
        "华为HMS": {
            "files": [r"huawei\-hms.*\.jar$", r"hms\-sdk.*\.aar$"],
            "patterns": [
                r"com\.huawei\.hms",
                r"HuaweiApiAvailability",
                r"HmsCore"
            ],
            "category": "移动服务",
            "main_framework": False,
            "features": ["华为移动服务", "推送通知", "地图服务", "支付服务", "账号服务"]
        },
        "百度BDUI": {
            "files": [r"bdui.*\.jar$", r"bdui\-sdk.*\.aar$"],
            "patterns": [
                r"com\.baidu\.bdui",
                r"BDUIContext",
                r"BDUIComponent"
            ],
            "category": "UI框架",
            "main_framework": True,
            "features": ["百度开发的跨平台UI框架", "高性能渲染", "组件化设计"]
        },
        "小米MIUI SDK": {
            "files": [r"miui\-sdk.*\.jar$", r"miuisdk.*\.aar$"],
            "patterns": [
                r"com\.xiaomi\.miuisdk",
                r"MiuiAPI",
                r"MiuiSettings"
            ],
            "category": "系统增强",
            "main_framework": False,
            "features": ["小米MIUI系统增强SDK", "系统特性支持", "推送服务"]
        },
        "OPPO ColorOS SDK": {
            "files": [r"coloros\-sdk.*\.jar$", r"oppo\-sdk.*\.aar$"],
            "patterns": [
                r"com\.coloros\.mcssdk",
                r"com\.oppo\.sdklib",
                r"OppoMcsService"
            ],
            "category": "系统增强",
            "main_framework": False,
            "features": ["OPPO ColorOS系统增强SDK", "推送服务", "系统特性支持"]
        },
        "vivo PushSDK": {
            "files": [r"vivo\-push.*\.jar$", r"vivopush.*\.aar$"],
            "patterns": [
                r"com\.vivo\.push",
                r"PushClient",
                r"VivoMessageReceiver"
            ],
            "category": "推送服务",
            "main_framework": False,
            "features": ["vivo设备推送服务", "系统级低功耗推送"]
        },
        "UCloud-UMeng": {
            "files": [r"umeng\-.*\.jar$", r"umeng.*\.aar$"],
            "patterns": [
                r"com\.umeng",
                r"UMConfigure",
                r"MobclickAgent"
            ],
            "category": "应用分析",
            "main_framework": False,
            "features": ["友盟应用分析服务", "用户行为分析", "设备统计", "推送服务"]
        },
        "极光JPush": {
            "files": [r"jpush\-.*\.jar$", r"jpush.*\.aar$"],
            "patterns": [
                r"cn\.jpush\.android",
                r"JPushInterface",
                r"JPushMessageReceiver"
            ],
            "category": "推送服务",
            "main_framework": False,
            "features": ["极光推送服务", "推送统计", "用户标签"]
        },
        "uni-app": {
            "files": [r"uni\-app.*\.js$", r"uni\-app.*\.json$", r"uniapp.*\.so$", r"uniapp\.js$", r"lib/plus/"],
            "patterns": [
                r"uni\-app",
                r"uni\.",
                r"getApp\(\)",
                r"uniCloud",
                r"pages\.json"
            ],
            "category": "跨平台框架",
            "main_framework": True,
            "features": ["DCloud开发的跨平台框架", "使用Vue.js开发", "一套代码多端运行", "国内流行的小程序开发方案"]
        },
        "uView": {
            "files": [r"uview.*\.js$", r"uview.*\.vue$", r"uview\-ui"],
            "patterns": [
                r"uview\-ui",
                r"import uView from",
                r"u\-"
            ],
            "category": "UI组件库",
            "main_framework": False,
            "features": ["uni-app生态的UI框架", "丰富的组件", "中文文档完善", "国内广泛使用"]
        }
    }
    
    def __init__(self, app_path: str, config: dict = None, verbose: bool = False):
        """
        初始化Android应用分析器
        
        Args:
            app_path: 应用程序路径
            config: 配置信息
            verbose: 是否输出详细日志
        """
        super().__init__(app_path, config, verbose)
        self.logger = get_logger("AndroidAnalyzer")
        self.logger.info(f"初始化Android应用分析器: {app_path}")
        
        # 合并配置和默认框架特征
        self.framework_signatures = self.FRAMEWORK_SIGNATURES.copy()
        if "frameworks" in self.config:
            for fw_name, fw_data in self.config["frameworks"].items():
                if fw_name in self.framework_signatures:
                    # 更新现有框架
                    for key, values in fw_data.items():
                        if key in self.framework_signatures[fw_name]:
                            self.framework_signatures[fw_name][key].extend(values)
                        else:
                            self.framework_signatures[fw_name][key] = values
                else:
                    # 添加新框架
                    self.framework_signatures[fw_name] = fw_data
    
    def analyze(self) -> AnalysisResult:
        """
        分析Android应用程序，识别使用的框架和技术栈
        
        Returns:
            AnalysisResult: 分析结果对象
        """
        self.logger.info(f"开始分析Android应用: {self.app_path}")
        
        result = AnalysisResult(
            app_path=str(self.app_path),
            platform="Android",
            analysis_time=datetime.now()
        )
        
        # 尝试检测应用程序信息
        app_info = self.detect_app_info()
        if app_info:
            result.app_name = app_info.name
            result.app_version = app_info.version
            result.metadata["app_identifier"] = app_info.identifier
            
            # 记录应用信息
            self.logger.info(f"应用信息: 名称={app_info.name}, 版本={app_info.version}, 包名={app_info.identifier}")
        
        # 扫描应用程序文件
        extensions = ['.xml', '.dex', '.jar', '.so', '.kt', '.java', '.json', '.smali']
        files = self.scan_files(extensions)
        
        self.logger.info(f"扫描到 {len(files)} 个文件，开始分析框架")
        
        # 识别框架特征
        for framework_name, signature in self.framework_signatures.items():
            # 搜索签名特征
            matched_files = self.search_signatures(files, 
                                               signature.get('files', []), 
                                               signature.get('patterns', []))
            
            if matched_files:
                confidence = min(0.3 + (len(matched_files) * 0.1), 0.9)  # 根据匹配文件数量增加信心值，最高0.9
                
                framework_info = FrameworkInfo(
                    name=framework_name,
                    confidence=confidence,
                    features=signature.get('features', []),
                    files=matched_files[:5],  # 只保留前5个文件作为示例
                    category=signature.get('category', '其他'),  # 使用新的类别属性
                    is_main=signature.get('main_framework', False)  # 使用新的主框架属性
                )
                
                # 为不同框架添加特定特征
                if framework_name == "Native Android":
                    framework_info.features.append("使用原生Android开发")
                elif framework_name == "Flutter":
                    framework_info.features.append("Google开发的跨平台UI框架")
                elif framework_name == "React Native":
                    framework_info.features.append("使用JavaScript的跨平台开发框架")
                elif framework_name == "Xamarin":
                    framework_info.features.append("使用C#的跨平台开发框架")
                elif framework_name == "Unity":
                    framework_info.features.append("流行的游戏开发引擎")
                elif framework_name == "Jetpack Compose":
                    framework_info.features.append("Android现代声明式UI框架")
                elif framework_name == "Unreal Engine":
                    framework_info.features.append("使用Unreal Engine的游戏开发引擎")
                elif framework_name == "Cocos2d-x":
                    framework_info.features.append("使用Cocos2d-x的游戏开发引擎")
                elif framework_name == "Godot":
                    framework_info.features.append("使用Godot的游戏开发引擎")
                elif framework_name == "LibGDX":
                    framework_info.features.append("使用LibGDX的游戏开发引擎")
                elif framework_name == "GameMaker":
                    framework_info.features.append("使用GameMaker的游戏开发引擎")
                else:
                    framework_info.features.append(f"{framework_name}技术特征")
                
                result.add_framework(framework_info)
                self.logger.info(f"检测到框架: {framework_name}, 信心值: {confidence:.2f}")
        
        self.logger.info(f"分析完成，共检测到 {len(result.frameworks)} 个框架")
        return result
    
    def detect_app_info(self) -> AppInfo:
        """
        从AndroidManifest.xml提取应用信息
        
        Returns:
            AppInfo: 应用程序的基本信息
        """
        app_name = None
        app_version = None
        app_identifier = None
        app_path = Path(self.app_path)
        
        # 查找AndroidManifest.xml文件
        manifest_paths = list(app_path.glob("**/AndroidManifest.xml"))
        
        if not manifest_paths:
            self.logger.warning("未找到AndroidManifest.xml文件")
            return AppInfo(
                name=app_path.stem,
                version=None,
                identifier=None,
                platform="Android"
            )
        
        # 解析AndroidManifest.xml
        manifest_path = manifest_paths[0]
        self.logger.info(f"找到AndroidManifest.xml: {manifest_path}")
        
        try:
            import xml.etree.ElementTree as ET
            import re
            
            # 判断是否为二进制格式(APK解包后可能是二进制格式)
            try:
                ET.parse(manifest_path)
                is_binary = False
            except:
                is_binary = True
            
            if is_binary:
                # 尝试使用apktool的输出
                resource_paths = list(app_path.glob("**/res/values/strings.xml"))
                if resource_paths:
                    try:
                        tree = ET.parse(resource_paths[0])
                        root = tree.getroot()
                        for item in root.findall(".//string"):
                            name = item.get('name')
                            if name == 'app_name':
                                app_name = item.text
                    except Exception as e:
                        self.logger.error(f"解析strings.xml失败: {e}")
                        
                # 尝试提取版本信息
                yml_paths = list(app_path.glob("**/apktool.yml"))
                if yml_paths:
                    try:
                        with open(yml_paths[0], 'r', encoding='utf-8') as f:
                            content = f.read()
                            version_match = re.search(r'versionName:\s*[\'"]?(.*?)[\'"]?$', content, re.MULTILINE)
                            if version_match:
                                app_version = version_match.group(1)
                    except Exception as e:
                        self.logger.error(f"解析apktool.yml失败: {e}")
            else:
                # 文本格式AndroidManifest.xml
                try:
                    tree = ET.parse(manifest_path)
                    root = tree.getroot()
                    
                    # 获取包名和版本
                    manifest = root
                    package = manifest.get('{http://schemas.android.com/apk/res/android}package') or manifest.get('package')
                    version = manifest.get('{http://schemas.android.com/apk/res/android}versionName')
                    
                    if package:
                        app_name = package
                        app_identifier = package
                    if version:
                        app_version = version
                        
                    # 查找应用标签
                    for app_tag in root.findall('.//application'):
                        label = app_tag.get('{http://schemas.android.com/apk/res/android}label')
                        if label:
                            # 处理资源引用
                            if label.startswith('@string/'):
                                # 尝试查找对应的字符串资源
                                resource_paths = list(app_path.glob("**/res/values/strings.xml"))
                                if resource_paths:
                                    try:
                                        res_tree = ET.parse(resource_paths[0])
                                        res_root = res_tree.getroot()
                                        res_name = label.split('/')[-1]
                                        for string in res_root.findall(".//string[@name='{}']".format(res_name)):
                                            app_name = string.text
                                            break
                                    except Exception as e:
                                        self.logger.error(f"解析字符串资源失败: {e}")
                            else:
                                app_name = label
                except Exception as e:
                    self.logger.error(f"解析AndroidManifest.xml失败: {e}")
                    
                    # 尝试使用正则表达式提取
                    try:
                        with open(manifest_path, 'r', encoding='utf-8', errors='ignore') as f:
                            content = f.read()
                        
                        # 提取包名
                        package_match = re.search(r'package\s*=\s*["\']([^"\']+)["\']', content)
                        if package_match:
                            app_identifier = package_match.group(1)
                            if not app_name:
                                app_name = app_identifier
                            
                        # 提取版本
                        version_match = re.search(r'android:versionName\s*=\s*["\']([^"\']+)["\']', content)
                        if version_match:
                            app_version = version_match.group(1)
                    except Exception as e:
                        self.logger.error(f"使用正则表达式解析AndroidManifest.xml失败: {e}")
        except Exception as e:
            self.logger.error(f"提取应用信息失败: {e}")
        
        return AppInfo(
            name=app_name or app_path.stem,
            version=app_version,
            identifier=app_identifier,
            platform="Android"
        ) 
